package org.jeecg.modules.demo.DPT.job;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.aliyun.dingtalkworkflow_1_0.Client;
import com.aliyun.dingtalkworkflow_1_0.models.GetProcessInstanceResponse;
import com.aliyun.dingtalkworkflow_1_0.models.GetProcessInstanceResponseBody;
import com.aliyun.dingtalkworkflow_1_0.models.ListProcessInstanceIdsResponse;
import com.aliyun.tea.TeaException;
import com.aliyun.teautil.models.RuntimeOptions;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiGettokenRequest;
import com.dingtalk.api.response.OapiGettokenResponse;
import com.google.gson.Gson;
import com.kingdee.bos.webapi.entity.IdentifyInfo;
import com.kingdee.bos.webapi.entity.RepoRet;
import com.kingdee.bos.webapi.sdk.K3CloudApi;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.modules.demo.DPT.entity.Ticket;
import org.jeecg.modules.demo.DPT.service.ITicketService;
import org.jeecg.modules.demo.Kingdee.util.AttachmentUploadUtil;
import org.jeecg.modules.demo.util.TicketUtil;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;

import java.io.*;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 进项发票更新标记（报销、付款、金蝶下推发票单据）
 * 
 * @Author Scott
 */
@Slf4j
public class UpdateTicketStatusJob implements Job {
	@Autowired
	ITicketService ticketService;
	/**
	 * <b>description</b> :
	 * <p>使用 Token 初始化账号Client</p>
	 * @return Client
	 *
	 * @throws Exception
	 */
	public static com.aliyun.dingtalkworkflow_1_0.Client createClient() throws Exception {
		com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config();
		config.protocol = "https";
		config.regionId = "central";
		return new com.aliyun.dingtalkworkflow_1_0.Client(config);
	}
	@SneakyThrows
	@Override
	public void execute(JobExecutionContext jobExecutionContext) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(new Date());
		calendar.add(Calendar.MONTH, -2);
		String ticketdateTwoMonthAgo = sdf.format(calendar.getTime());

		long starttime = calendar.getTime().getTime();
		long endtime = System.currentTimeMillis();
		String parameter = jobExecutionContext.getMergedJobDataMap().getString("parameter");
		if (parameter!=null&&!parameter.isEmpty()){
			String[] split = parameter.split(",");
			ticketdateTwoMonthAgo=split[0];
			if(split.length>1){
				Date date = sdf.parse(split[1]);
				endtime = date.getTime();
			}
		}
		String baoxiaoCode="PROC-C2B18DBD-C027-47DB-8A8E-68224415CD80";
		String fukuanCode="PROC-370AB924-D808-4792-9D19-8C495DE7B23A";
		updateTicketStatus("报销",baoxiaoCode,starttime,endtime);
		updateTicketStatus("付款申请",fukuanCode,starttime,endtime);
		updateTicketFromKD(ticketdateTwoMonthAgo);
	}


	private void updateTicketStatus(String type,String code,long starttime,long endtime) throws Exception {
		String detailLabel;
		if(type.equals("报销")){
			detailLabel=type;
		}else {
			detailLabel="付款";
		}
		Client client = createClient();
		DingTalkClient client1 = new DefaultDingTalkClient("https://oapi.dingtalk.com/gettoken");
		OapiGettokenRequest req = new OapiGettokenRequest();
		req.setAppkey("dingy4ty1ij8uookoz5b");
		req.setAppsecret("6IdNwkz1u7wxf80uJJr6N73G5Yi0U_Wl9JHRlfHBKiMgTDIbJ1H_0mSSi_bBA0XQ");
		req.setHttpMethod("GET");
		OapiGettokenResponse rsp = client1.execute(req);

		com.aliyun.dingtalkworkflow_1_0.models.ListProcessInstanceIdsHeaders listProcessInstanceIdsHeaders = new com.aliyun.dingtalkworkflow_1_0.models.ListProcessInstanceIdsHeaders();

		listProcessInstanceIdsHeaders.xAcsDingtalkAccessToken = rsp.getAccessToken();

		com.aliyun.dingtalkworkflow_1_0.models.GetProcessInstanceHeaders getProcessInstanceHeaders = new com.aliyun.dingtalkworkflow_1_0.models.GetProcessInstanceHeaders();
		getProcessInstanceHeaders.xAcsDingtalkAccessToken = rsp.getAccessToken();

		String nexttoken = "0";
		com.aliyun.dingtalkworkflow_1_0.models.ListProcessInstanceIdsRequest listProcessInstanceIdsRequest = new com.aliyun.dingtalkworkflow_1_0.models.ListProcessInstanceIdsRequest()
				.setStartTime(starttime)
				.setEndTime(endtime)
				.setProcessCode(code)
				.setMaxResults(20L);

		Map<String, List> resultMap = new HashMap<>();
		try {
			while (nexttoken!=null&&!nexttoken.isEmpty()){
//				为下次循环使用
				listProcessInstanceIdsRequest.setNextToken(Long.valueOf(nexttoken));
				ListProcessInstanceIdsResponse response = client.listProcessInstanceIdsWithOptions(listProcessInstanceIdsRequest, listProcessInstanceIdsHeaders, new RuntimeOptions());
				nexttoken = response.getBody().getResult().getNextToken();
				List<String> list = response.getBody().getResult().getList();
				for (String id : list) {
					com.aliyun.dingtalkworkflow_1_0.models.GetProcessInstanceRequest getProcessInstanceRequest = new com.aliyun.dingtalkworkflow_1_0.models.GetProcessInstanceRequest()
							.setProcessInstanceId(id);
					GetProcessInstanceResponse instance = client.getProcessInstanceWithOptions(getProcessInstanceRequest, getProcessInstanceHeaders, new RuntimeOptions());
//				审批编号
					String businessId = instance.getBody().getResult().getBusinessId();
					if(!resultMap.containsKey(businessId)){
						resultMap.put(businessId,new ArrayList());
					}
					List<GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResultFormComponentValues> formComponentValues = instance.getBody().getResult().getFormComponentValues();
					for (GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResultFormComponentValues formComponentValue : formComponentValues) {
						String name = formComponentValue.getName();
						if(name!=null&&name.equals(detailLabel+"明细")){
							String value = formComponentValue.getValue();
							JSONArray objects = JSONArray.parseArray(value);
							for (Object object : objects) {
								JSONObject detail = (JSONObject) object;
								for (Object rowValue : detail.getJSONArray("rowValue")) {
									String label = ((JSONObject) rowValue).getString("label");
									if(label.equals("发票")){
										JSONArray invoiceList = ((JSONObject) rowValue).getJSONObject("extendValue").getJSONArray("invoiceList");
										if(invoiceList!=null){
											for (Object invoice : invoiceList) {
												String invoiceNo = ((JSONObject) invoice).getString("invoiceNo");
												resultMap.get(businessId).add(invoiceNo);
											}
										}
									}
								}
							}
						}
//						报销原来是明细中的发票，8.11号修改为主表中的发票（9.27再次修改，为了使用打印模板，模板只能打印明细中的发票图片）
						if(type.equals("报销")&&name!=null&&name.equals("发票")){
							String extValue = formComponentValue.getExtValue();
							if(extValue!=null&&!extValue.isEmpty()){
								JSONObject extValueObj = JSONObject.parseObject(extValue);
								if(extValueObj.getJSONArray("invoiceList")!=null){
									for (Object o : extValueObj.getJSONArray("invoiceList")) {
										JSONObject invoice = (JSONObject) o;
										String invoiceNo = invoice.getString("invoiceNo");
										resultMap.get(businessId).add(invoiceNo);
									}
								}
							}
						}
					}
				}
			}

			resultMap.forEach((k,v)->{
				if(!v.isEmpty()){
					for (Object no : v) {
						Ticket fphm = ticketService.query().eq("fphm", no.toString()).one();
						if(fphm!=null){
							log.info(fphm.getFphm()+"匹配"+type+"成功");
							fphm.setOanumber(k);
							fphm.setProjecttype(type);
							ticketService.updateById(fphm);
						}
					}
				}
			});
		}  catch (Exception _err) {
			TeaException err = new TeaException(_err.getMessage(), _err);
			log.error(err.message);
			err.printStackTrace();
		}
	}

	private K3CloudApi api;
	public void updateTicketFromKD(String date) throws Exception {
		List<Ticket> list = ticketService.query()
				.eq("projecttype", "未关联")
				.ge("tickettime",date)
				.isNotNull("downloadurl")
				.list();
		Properties properties = new Properties();
		ClassPathResource resource = new ClassPathResource("kdwebapi.properties");
		InputStream inputStream = resource.getInputStream();
//		File file = new File((new File("./java_sdk_demo/src")).getCanonicalPath() + "/kdwebapi.properties");
//		System.out.println("读取根目录下的配置文件->" + file.getPath());
//		InputStream inputStream = new FileInputStream(file.getPath());
		properties.load(new InputStreamReader(inputStream, "utf-8"));
		inputStream.close();
		IdentifyInfo iden = new IdentifyInfo();
		iden.setUserName(properties.getProperty("X-KDApi-UserName"));
		iden.setAppId(properties.getProperty("X-KDApi-AppID"));
		iden.setdCID(properties.getProperty("X-KDApi-AcctID"));
		iden.setAppSecret(properties.getProperty("X-KDApi-AppSec"));
		iden.setlCID(2052);
		iden.setServerUrl(properties.getProperty("X-KDApi-ServerUrl"));
		this.api = new K3CloudApi(iden);
		for (Ticket ticket : list) {
			if(ticket.getDownloadurl()==null||ticket.getDownloadurl().isEmpty()){
				continue;
			}
			BigDecimal kpje = ticket.getKpje();
			String khmc = ticket.getKhmc();
			String  data1 = "{\"FormId\":\"ORG_Organizations\",\"FieldKeys\":\"FORGID\",\"FilterString\":\"FNAME= '"+khmc+"'\"}";
			List<List<Object>> lists1 = api.executeBillQuery(data1);
			if(!lists1.isEmpty()){
				String ORGID = lists1.get(0).get(0).toString();
				String  SUPPLIERParm = "{\"FormId\":\"BD_Supplier\",\"FieldKeys\":\"FNAME,FSUPPLIERID\",\"FilterString\":\"FNAME= '"+ticket.getXfmc()+"' AND FUSEORGID="+ORGID+"\"}";
				List<List<Object>> SUPPLIERP = api.executeBillQuery(SUPPLIERParm);
				if(!SUPPLIERP.isEmpty()){
					SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
					Calendar calendar = Calendar.getInstance();
					calendar.setTime(ticket.getTickettime());
					String ticketdate = sdf.format(calendar.getTime());
					calendar.add(Calendar.MONTH, -2);
					String ticketdateTwoMonthAgo = sdf.format(calendar.getTime());

					String supplierId = SUPPLIERP.get(0).get(1).toString();
					String data = String.format("{\"FormId\":\"AP_PAYABLE\",\"FieldKeys\":\"FBillNo,FALLAMOUNTFOR\",\"FilterString\":\"FALLAMOUNTFOR= %f AND FSUPPLIERID=%s AND FDATE>='%s' AND FDATE<='%s'\"}",
							kpje.doubleValue(),supplierId,ticketdateTwoMonthAgo,ticketdate);
					List<List<Object>> lists = api.executeBillQuery(data);
					if (lists.size()==1){
						//相同供应商+金额的情况不做标记
						log.info("应付单据："+lists.get(0).get(0).toString()+"匹配到发票号码："+ticket.getFphm());
						ticket.setOanumber(lists.get(0).get(0).toString());
						ticket.setProjecttype("金蝶应付单");
						ticketService.updateById(ticket);
//						金蝶下推发票
						IV_PayablePushPurchaseIC(lists.get(0).get(0).toString(),ticket.getFphm(),ticket.getDownloadurl(),ticketdate);
						log.info("金蝶下推发票成功");
//						break;
					}
				}
			}
		}
	}

	public void IV_PayablePushPurchaseIC(String BillNo,String fphm,String ticketurl,String ticketdate) throws Exception {
//		下推采购增值税发票
		String  paradata =String.format("{\"Numbers\": [\"%s\"],\"EntryIds\": \"\",\"RuleId\": \"IV_PayableToPurchaseIC\"}", BillNo) ;
		String result = api.push("AP_Payable", paradata);
		Gson gson = new Gson();
		RepoRet repoRet = gson.fromJson(result, RepoRet.class);
		if (repoRet.getResult().getResponseStatus().isIsSuccess()) {
			String entity = gson.toJson(repoRet.getResult().getResponseStatus().getSuccessEntitys().get(0));
			String POChangeid = JSONObject.parseObject(entity).getString("Id");

			String json=String.format("  {\n" +
					"\"NeedUpDateFields\": [\n" +
					"\"FREMARK\",\"FINVOICEDATE\",\"FINVOICENO\"\n" +
					"],\n" +
					"\"IsDeleteEntry\": \"false\",\n" +
					"            \"SubSystemId\": \"\",\n" +
					"            \"IsVerifyBaseDataField\": \"false\",\n" +
					"            \"IsEntryBatchFill\": \"True\",\n" +
					"            \"IsAutoSubmitAndAudit\": \"false\","+
					"            \"NeedReturnFields\": [],"+
					"\"Model\": {\n" +
					"\"FID\": %s,\n" +
					"\"FREMARK\": \"电票通自动匹配\",\n" +
					"\"FREMARK\": \"电票通自动匹配\",\n" +
					"\"FINVOICEDATE\": \"%s\",\n" +
					"\"FINVOICENO\": \"%s\"\n" +
					"}\n" +
					"}\n",POChangeid,ticketdate,fphm);

//			更新发票号码和备注
			String result1 = api.save("IV_PURCHASEIC", json);
			System.out.printf(result1);
			if(ticketurl!=null&&!ticketurl.isEmpty()){
				InputStream inputStream = TicketUtil.getFileInputStreamWithoutClosing(ticketurl, null).getInputStream();
				// 使用工具类方法替换原来的AttachmentUpload方法
				AttachmentUploadUtil.uploadAttachment(fphm + ".pdf", "IV_PURCHASEIC", BillNo, POChangeid, inputStream);
			}
//			保存提交审核
			String submitjson=String.format("{\"Ids\": %s}",POChangeid);
			String result2 = api.submit("IV_PURCHASEIC", submitjson);
			System.out.println(result2);
		} else {
//			fail("采购订单下推采购变更单接口: " + result );
		}
	}

}
